package model;
/*
 @(#)TicTacToe.java	1.2 95/10/13 
 *
 * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
 * without fee is hereby granted. 
 * Please refer to the file http://java.sun.com/copy_trademarks.html
 * for further important copyright and trademark information and to
 * http://java.sun.com/licensing.html for further important licensing
 * information for the Java (tm) Technology.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 * 
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  SUN
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 */

//import java.awt.*;
//import java.awt.image.*;
//import java.net.*;
//import java.applet.*;

/**
 * A TicTacToe applet. A very simple, and mostly brain-dead
 * implementation of your favorite game! <p>
 *
 * In this game a position is represented by a white and black
 * bitmask. A bit is set if a position is ocupied. There are
 * 9 squares so there are 1<<9 possible positions for each
 * side. An array of 1<<9 booleans is created, it marks
 * all the winning positions.
 *
 * @version 	1.2, 13 Oct 1995
 * @author Arthur van Hoff
 * @modified 96/04/23 Jim Hagen : winning sounds
 * extends Applet
 * 
 * Modified for Michi
 */
public
class ComputerTicTacToe  {
	/**
	 * White's current position. The computer is white.
	 */
	int white;

	/**
	 * Black's current position. The user is black.
	 */
	int black;

	/**
	 * The squares in order of importance...
	 */
	final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};

	/**
	 * The winning positions.
	 */
	static boolean won[] = new boolean[1 << 9];
	static final int DONE = (1 << 9) - 1;
	static final int OK = 0;
	public static final int WIN = 1;
	public static final int LOSE = 2;
	public static final int STALEMATE = 3;

	/**
	 * Mark all positions with these bits set as winning.
	 */
	static void isWon(int pos) {
		for (int i = 0 ; i < DONE ; i++) {
			if ((i & pos) == pos) {
				won[i] = true;
			}
		}
	}

	/**
	 * Initialize all winning positions.
	 */
	static {
		isWon((1 << 0) | (1 << 1) | (1 << 2));
		isWon((1 << 3) | (1 << 4) | (1 << 5));
		isWon((1 << 6) | (1 << 7) | (1 << 8));
		isWon((1 << 0) | (1 << 3) | (1 << 6));
		isWon((1 << 1) | (1 << 4) | (1 << 7));
		isWon((1 << 2) | (1 << 5) | (1 << 8));
		isWon((1 << 0) | (1 << 4) | (1 << 8));
		isWon((1 << 2) | (1 << 4) | (1 << 6));
	}

	/**
	 * Compute the best move for white.
	 * @return the square to take
	 */
	int bestMove(int white, int black) {
		int bestmove = -1;

		loop:
			for (int i = 0 ; i < 9 ; i++) {
				int mw = moves[i];
				if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
					int pw = white | (1 << mw);
					if (won[pw]) {
						// white wins, take it!
						return mw;
					}
					for (int mb = 0 ; mb < 9 ; mb++) {
						if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) {
							int pb = black | (1 << mb);
							if (won[pb]) {
								// black wins, take another
								continue loop;
							}
						}
					}
					// Neither white nor black can win in one move, this will do.
					if (bestmove == -1) {
						bestmove = mw;
					}
				}
			}
		if (bestmove != -1) {
			return bestmove;
		}

		// No move is totally satisfactory, try the first one that is open
		for (int i = 0 ; i < 9 ; i++) {
			int mw = moves[i];
			if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
				return mw;
			}
		}

		// No more moves
		return -1;
	}

	/**
	 * User move.
	 * @return true if legal
	 */
	public boolean yourMove(int m) {

		if (status() != OK)
			return false;

		if ((m < 0) || (m > 8)) {
			return false;
		}
		if (((black | white) & (1 << m)) != 0) {
			return false;
		}
		black |= 1 << m;
		return true;
	}

	/**
	 * Computer move.
	 * @return true if legal
	 */
	public int myMove() {
		if ((black | white) == DONE) {
			return -1;
		}
		int best = bestMove(white, black);
		white |= 1 << best;
		
		return best; 
	}

	/**
	 * Figure what the status of the game is.
	 */
	public int status() {

		if (won[black]) {
			return LOSE;// person has priority!
		}

		if (won[white]) {
			return WIN;
		}

		if ((black | white) == DONE) {
			return STALEMATE;
		}
		return OK;
	}



	/**
	 * Who goes first in the next game?
	 */
	boolean first = true;

	/**
	 * The image for white.
	 */
	//    Image notImage;
	//
	//    /**
	//     * The image for black.
	//     */
	//    Image crossImage;
	//
	//    /**
	//     * Initialize the applet. Resize and load images.
	//     */
	//    public void init() {
	//	notImage = getImage(getCodeBase(), "images/not.gif");
	//	crossImage = getImage(getCodeBase(), "images/cross.gif");
	//    }
	//
	//    /**
	//     * Paint it.
	//     */
	//    public void paint(Graphics g) {
	//	Dimension d = size();
	//	g.setColor(Color.black);
	//	int xoff = d.width / 3;
	//	int yoff = d.height / 3;
	//	g.drawLine(xoff, 0, xoff, d.height);
	//	g.drawLine(2*xoff, 0, 2*xoff, d.height);
	//	g.drawLine(0, yoff, d.width, yoff);
	//	g.drawLine(0, 2*yoff, d.width, 2*yoff);
	//
	//	int i = 0;
	//	for (int r = 0 ; r < 3 ; r++) {
	//	    for (int c = 0 ; c < 3 ; c++, i++) {
	//		if ((white & (1 << i)) != 0) {
	//		    g.drawImage(notImage, c*xoff + 1, r*yoff + 1, this);
	//		} else if ((black & (1 << i)) != 0) {
	//		    g.drawImage(crossImage, c*xoff + 1, r*yoff + 1, this);
	//		}
	//	    }
	//	}
	//    }
	//
	//    /**
	//     * The user has clicked in the applet. Figure out where
	//     * and see if a legal move is possible. If it is a legal
	//     * move, respond with a legal move (if possible).
	//     */
	//    public boolean mouseUp(Event evt, int x, int y) {
	//	switch (status()) {
	//	  case WIN:
	//	  case LOSE:
	//	  case STALEMATE:
	//	    play(getCodeBase(), "audio/return.au");
	//	    white = black = 0;
	//	    if (first) {
	//		white |= 1 << (int)(Math.random() * 9);
	//	    }
	//	    first = !first;
	//	    repaint();
	//	    return true;
	//	}
	//
	//	// Figure out the row/colum
	//	Dimension d = size();
	//	int c = (x * 3) / d.width;
	//	int r = (y * 3) / d.height;
	//	if (yourMove(c + r * 3)) {
	//	    repaint();
	//
	//	    switch (status()) {
	//	      case WIN:
	//		play(getCodeBase(), "audio/yahoo1.au");
	//		break;
	//	      case LOSE:
	//		play(getCodeBase(), "audio/yahoo2.au");
	//		break;
	//	      case STALEMATE:
	//		break;
	//	      default:
	//		if (myMove()) {
	//		    repaint();
	//		    switch (status()) {
	//		      case WIN:
	//			play(getCodeBase(), "audio/yahoo1.au");
	//			break;
	//		      case LOSE:
	//			play(getCodeBase(), "audio/yahoo2.au");
	//			break;
	//		      case STALEMATE:
	//			break;
	//		      default:
	//			play(getCodeBase(), "audio/ding.au");
	//		    }
	//		} else {
	//		    play(getCodeBase(), "audio/beep.au");
	//		}
	//	    }
	//	} else {
	//	    play(getCodeBase(), "audio/beep.au");
	//	}
	//	return true;
	//    }
	//
	//    public String getAppletInfo() {
	//	return "TicTacToe by Arthur van Hoff";
	//    }
}